package com.kefu.chat.service;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import com.kefu.chat.model.ChatAdmin;
import com.kefu.chat.model.ChatChannel;
import com.kefu.chat.model.ChatData;
import com.kefu.chat.model.ChatUser;
import com.kefu.chat.util.ChatConstant;
import com.kefu.chat.vo.ChatEventMsg.BaseMsgE;
import com.kefu.common.util.JacksonUtil;

import cn.hutool.core.util.StrUtil;
import lombok.extern.slf4j.Slf4j;


@Slf4j
@Service
@SuppressWarnings("all")
public class ChatCacheService {
    private final int max_select_size = 99;
    @Autowired
    private StringRedisTemplate redisTemplate;
    @Autowired
    private ChatChannelService chatChannelService;
    
    @Autowired
    private ChatShareService chatShareService;

    public ChatUser getUser(String id) {
    	return chatShareService.getUser(id);
    }

    public void setUser(ChatUser user) {
        chatShareService.setUser(user);
    }


    public ChatAdmin getAdmin(String id) {
        return JacksonUtil.toBean(redisTemplate.opsForValue().get(ChatConstant.cache_chat_admin + id), ChatAdmin.class);
    }

    public void setAdmin(ChatAdmin admin) {
        log.info("setChatAdmin:{}", admin);
        redisTemplate.opsForValue().set(ChatConstant.cache_chat_admin + admin.getAdminId(), JacksonUtil.toString(admin), 16, TimeUnit.DAYS);
    }

    public ChatData getData(String sessionId) {
        return JacksonUtil.toBean(redisTemplate.opsForValue().get(ChatConstant.cache_chat_data + sessionId), ChatData.class);
    }

    public void setData(ChatData chatData) {
        redisTemplate.opsForValue().set(ChatConstant.cache_chat_data + chatData.getSessionId(), JacksonUtil.toString(chatData), 12, TimeUnit.HOURS);
    }


    public void addRobotSet(String tenantId, String sessionId) {
        redisTemplate.opsForSet().add(ChatConstant.cache_robot_set + tenantId, sessionId);
    }

    public void delRobotSet(String tenantId, String sessionId) {
        redisTemplate.opsForSet().remove(ChatConstant.cache_robot_set + tenantId, sessionId);
    }

    public Set<String> getRobotSet(String tenantId) {
        return redisTemplate.opsForSet().members(ChatConstant.cache_robot_set + tenantId);
    }

    public long getRobotSetSize(String tenantId) {
        return redisTemplate.opsForSet().size(ChatConstant.cache_robot_set + tenantId);
    }


    public long addWaitList(ChatUser user) {
        String key = ChatConstant.cache_wait_list + user.getTenantId();
        ChatChannel channel = chatChannelService.getFromId(user.getChannelId());
        long score = System.currentTimeMillis() / 1000;
        if ("vip".equals(channel.getQueueMode())) {
            score -= channel.getVipTime() * 60;
        }
        redisTemplate.opsForZSet().add(key, user.getUserId(), score);
        Set<String> set = redisTemplate.opsForZSet().rangeByScore(key, 0, score);
        return set.size();
    }

    public List<String> getWaitList(String tenantId) {
        String key = ChatConstant.cache_wait_list + tenantId;
        Set<String> set = redisTemplate.opsForZSet().range(key, 0, max_select_size);
        return set.stream().collect(Collectors.toList());
    }

    public void delWaitList(String tenantId, String userId) {
        redisTemplate.opsForZSet().remove(ChatConstant.cache_wait_list + tenantId, userId);
    }

    public void emptyWaitList(String tenantId) {
        redisTemplate.delete(ChatConstant.cache_wait_list + tenantId);
    }

    public long getWaitSize(String tenantId) {
        return redisTemplate.opsForZSet().size(ChatConstant.cache_wait_list + tenantId);
    }

    public long getWaitIndex(String tenantId, String userId) {
        return getWaitList(tenantId).indexOf(userId) + 1;
    }


    public void addAdminSet(String tenantId, String adminId) {
        redisTemplate.opsForSet().add(ChatConstant.cache_admin_set + tenantId, adminId);
    }

    public void delAdminSet(String tenantId, String adminId) {
        redisTemplate.opsForSet().remove(ChatConstant.cache_admin_set + tenantId, adminId);
    }

    public Set<String> getAdminSet(String tenantId) {
        return redisTemplate.opsForSet().members(ChatConstant.cache_admin_set + tenantId);
    }

    public long getAdminSetSize(String tenantId) {
        return redisTemplate.opsForSet().size(ChatConstant.cache_admin_set + tenantId);
    }

    public void addAdminUserSet(String adminId, String userId) {
        redisTemplate.opsForSet().add(ChatConstant.cache_admin_user_set + adminId, userId);
    }

    public Set<String> getAdminUserSet(String adminId) {
        return redisTemplate.opsForSet().members(ChatConstant.cache_admin_user_set + adminId);
    }

    public long getAdminUserSetSize(String adminId) {
        return redisTemplate.opsForSet().size(ChatConstant.cache_admin_user_set + adminId);
    }

    public void delAdminUserSet(String adminId, String userId) {
        redisTemplate.opsForSet().remove(ChatConstant.cache_admin_user_set + adminId, userId);
    }

    public void emptyAdminUserSet(String adminId) {
        redisTemplate.delete(ChatConstant.cache_admin_user_set + adminId);
    }


    public void sendEventMsg(String pollId, BaseMsgE msg) {
        if (StrUtil.isBlank(pollId) || msg == null) return;
        log.info("sendEventMsg:{},{}", pollId, msg);
        String msgKey = ChatConstant.cache_event_msg_list + pollId;
        redisTemplate.opsForList().rightPush(msgKey, JacksonUtil.toString(msg));
        redisTemplate.expire(msgKey, 1, TimeUnit.HOURS);
    }

    public List getEventMsg(String pollId) {
        if (StrUtil.isBlank(pollId)) return null;
        List list = new ArrayList();
        String msgKey = ChatConstant.cache_event_msg_list + pollId;
        long msgSize = redisTemplate.opsForList().size(msgKey);
        for (long i = 0; i < msgSize; i++) {
            String msgJson = (String) redisTemplate.opsForList().leftPop(msgKey);
            if (StrUtil.isNotBlank(msgJson)) {
                list.add(JacksonUtil.toMap(msgJson));
            }
        }
        return list;
    }


    public void sendOfflineMsg(String pollId, BaseMsgE msg) {
        if (StrUtil.isBlank(pollId) || msg == null) return;
        String msgKey = ChatConstant.cache_offline_msg_list + pollId;
        redisTemplate.opsForList().rightPush(msgKey, JacksonUtil.toString(msg));
        redisTemplate.expire(msgKey, 7, TimeUnit.DAYS);
    }

    public List getOfflineMsg(String pollId) {
        if (StrUtil.isBlank(pollId)) return null;
        List list = new ArrayList();
        String msgKey = ChatConstant.cache_offline_msg_list + pollId;
        long msgSize = redisTemplate.opsForList().size(msgKey);
        for (long i = 0; i < msgSize; i++) {
            String msgJson = (String) redisTemplate.opsForList().leftPop(msgKey);
            if (StrUtil.isNotBlank(msgJson)) {
                list.add(JacksonUtil.toMap(msgJson));
            }
        }
        return list;
    }


    public void setAdminPollTime(String tenantId, String adminId) {
        redisTemplate.opsForHash().put(ChatConstant.cache_admin_poll_time_hash + tenantId, adminId, System.currentTimeMillis() + "");
    }

    public void delAdminPollTime(String tenantId, String adminId) {
        redisTemplate.opsForHash().delete(ChatConstant.cache_admin_poll_time_hash + tenantId, adminId);
    }

    public Map getAdminPollTime(String tenantId) {
        return redisTemplate.opsForHash().entries(ChatConstant.cache_admin_poll_time_hash + tenantId);
    }


    public void setUserPollTime(String tenantId, String userId) {
        redisTemplate.opsForHash().put(ChatConstant.cache_user_poll_time_hash + tenantId, userId, System.currentTimeMillis() + "");
    }

    public void delUserPollTime(String tenantId, String userId) {
        redisTemplate.opsForHash().delete(ChatConstant.cache_user_poll_time_hash + tenantId, userId);
    }

    public Map getUserPollTime(String tenantId) {
        return redisTemplate.opsForHash().entries(ChatConstant.cache_user_poll_time_hash + tenantId);
    }

    public Object getUserPollTime(String tenantId, String userId) {
        return redisTemplate.opsForHash().get(ChatConstant.cache_user_poll_time_hash + tenantId, userId);
    }


}
